package com.vhuomai.store.provider;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.request.DelFileRequest;
import com.qcloud.cos.request.GetFileInputStreamRequest;
import com.qcloud.cos.request.StatFileRequest;
import com.qcloud.cos.request.UploadFileRequest;
import com.qcloud.cos.sign.Credentials;
import com.quanyue.auto.util.KeyGenerator;
import com.quanyue.auto.util.json.JsonMapper;
import com.vhuomai.store.entity.BaseStoreConfig;
import com.vhuomai.store.exception.StoreException;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.InputStream;

/**
 * @author harris
 */
public class CosStoreProvider implements StoreProvider {

    private static final String SUCCESS = "SUCCESS";
    private static final String ERROR_CMD_FILE_NOT_EXIST = "ERROR_CMD_FILE_NOTEXIST";
    private static final Logger LOGGER = LoggerFactory.getLogger(CosStoreProvider.class);

    @Override
    public String saveFile(BaseStoreConfig config, byte[] content, String ext) {
        String fileName = KeyGenerator.uuid() + ext;
        return this.saveFileByName(config, content, fileName);
    }

    @Override
    public String saveFileByName(BaseStoreConfig config, byte[] content, String fileName) throws StoreException {
        UploadFileRequest uploadFileRequest = new UploadFileRequest(config.getBucket(), "/" + config.getMerchantNo() + "/" + fileName, content);
        String response = this.createClient(config).uploadFile(uploadFileRequest);
        CosResult result = JsonMapper.fromJson(response, CosResult.class);
        if (SUCCESS.equals(result.getMessage())) {
            return config.getDomainUrl() + config.getMerchantNo() + "/" + fileName;
        } else {
            LOGGER.error("Save image fail, code {}, message: {}", result.getCode(), result.getMessage());
            throw new StoreException("图片保存失败," + result.getMessage());
        }
    }

    @Override
    public boolean fileExist(BaseStoreConfig config, String url) throws StoreException {
        String cosPath = url.substring(config.getDomainUrl().length());
        StatFileRequest request = new StatFileRequest(config.getBucket(), cosPath);
        CosResult result = JsonMapper.fromJson(this.createClient(config).statFile(request), CosResult.class);
        if (SUCCESS.equals(result.getMessage())) {
            return true;
        } else if (ERROR_CMD_FILE_NOT_EXIST.equals(result.getMessage())) {
            return false;
        } else {
            LOGGER.error("Save image fail, code {}, message: {}", result.getCode(), result.getMessage());
            throw new StoreException("获取图片失败," + result.getMessage());
        }
    }

    @Override
    public void remove(BaseStoreConfig config, String url) throws StoreException {
        String cosPath = url.substring(config.getDomainUrl().length());
        DelFileRequest request = new DelFileRequest(config.getBucket(), cosPath);
        CosResult result = JsonMapper.fromJson(this.createClient(config).delFile(request), CosResult.class);
        if (!SUCCESS.equals(result.getMessage())) {
            LOGGER.error("Save image fail, code {}, message: {}", result.getCode(), result.getMessage());
            throw new StoreException("图片保存失败," + result.getMessage());
        }
    }

    @Override
    public InputStream getContent(BaseStoreConfig config, String url) throws StoreException {
        String cosPath = url.substring(config.getDomainUrl().length());
        GetFileInputStreamRequest request = new GetFileInputStreamRequest(config.getBucket(), cosPath);
        try {
            return this.createClient(config).getFileInputStream(request);
        } catch (Exception e) {
            throw new StoreException("获取文件失败");
        }
    }

    private COSClient createClient(BaseStoreConfig config) throws StoreException {
        Credentials cred = new Credentials(Integer.valueOf(config.getAppId()), config.getSecretId(), config.getSecretKey());
        ClientConfig clientConfig = new ClientConfig();
        clientConfig.setRegion(config.getRegion());
        return new COSClient(clientConfig, cred);
    }

    @Data
    public static class CosResult {
        private int code;
        private String message;
        @JsonProperty("request_id")
        private String requestId;
        private DataBean data;

        @Data
        public static class DataBean {
            @JsonProperty("access_url")
            private String accessUrl;
            @JsonProperty("resource_path")
            private String resourcePath;
            @JsonProperty("source_url")
            private String sourceUrl;
            private String url;
            private String vid;
        }
    }
}
